<script>
export default {
  components: {},
  data () {
    return {
      radio: 0,
      activeName: '1',
    };
  },
  computed: {
    isButtonDisabled() {
      return this.radio === 0;
    }
  },
  methods: {
    check(radio) {
      console.log(radio)
      if (radio === 3) {
        this.$message.success('恭喜你，答对啦！')
      } else {
        this.$message.error('很遗憾，答错啦！')
      }
    },
  }
}
</script>

<template>
  <div>
    <div>
      <h1 align="center">2.2 GCC 编译参数解析</h1>
      <el-divider></el-divider>
      <b>GCC</b>
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-text"><span class="pln">$ wget </span><span class="pun">-</span><span class="pln">c http</span><span class="pun">:</span><span class="com">//www.mirrorservice.org/sites/sourceware.org/pub/gcc/releases/gcc-4.4.0/gcc-4.4.0.tar.bz2</span></code></li><li class="L1"><code class="lang-text"><span class="pln">$ tar </span><span class="pun">-</span><span class="pln">xjvf gcc</span><span class="pun">-</span><span class="lit">4.4</span><span class="pun">.</span><span class="lit">0.tar</span><span class="pun">.</span><span class="pln">bz2</span></code></li><li class="L2"><code class="lang-text"><span class="pln">$ </span><span class="pun">./</span><span class="pln">configure</span></code></li><li class="L3"><code class="lang-text"><span class="pln">$ make </span><span class="pun">&amp;&amp;</span><span class="pln"> sudo make install</span></code></li></ol></pre>
      <b>常用选项</b>
      <br>使用 gcc -v 可以查看默认开启的选项：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-text"><span class="pln">$ gcc </span><span class="pun">-</span><span class="pln">v</span></code></li><li class="L1"><code class="lang-text"><span class="typ">Using</span><span class="pln"> built</span><span class="pun">-</span><span class="kwd">in</span><span class="pln"> specs</span><span class="pun">.</span></code></li><li class="L2"><code class="lang-text"><span class="pln">COLLECT_GCC</span><span class="pun">=</span><span class="pln">gcc</span></code></li><li class="L3"><code class="lang-text"><span class="pln">COLLECT_LTO_WRAPPER</span><span class="pun">=</span><span class="str">/usr/</span><span class="pln">lib</span><span class="pun">/</span><span class="pln">gcc</span><span class="pun">/</span><span class="pln">x86_64</span><span class="pun">-</span><span class="pln">linux</span><span class="pun">-</span><span class="pln">gnu</span><span class="pun">/</span><span class="lit">5</span><span class="pun">/</span><span class="pln">lto</span><span class="pun">-</span><span class="pln">wrapper</span></code></li><li class="L4"><code class="lang-text"><span class="typ">Target</span><span class="pun">:</span><span class="pln"> x86_64</span><span class="pun">-</span><span class="pln">linux</span><span class="pun">-</span><span class="pln">gnu</span></code></li><li class="L5"><code class="lang-text"><span class="typ">Configured</span><span class="pln"> </span><span class="kwd">with</span><span class="pun">:</span><span class="pln"> </span><span class="pun">../</span><span class="pln">src</span><span class="pun">/</span><span class="pln">configure </span><span class="pun">-</span><span class="pln">v </span><span class="pun">--</span><span class="kwd">with</span><span class="pun">-</span><span class="pln">pkgversion</span><span class="pun">=</span><span class="str">'Ubuntu 5.4.0-6ubuntu1~16.04.9'</span><span class="pln"> </span><span class="pun">--</span><span class="kwd">with</span><span class="pun">-</span><span class="pln">bugurl</span><span class="pun">=</span><span class="pln">file</span><span class="pun">:</span><span class="com">///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu</span></code></li><li class="L6"><code class="lang-text"><span class="typ">Thread</span><span class="pln"> model</span><span class="pun">:</span><span class="pln"> posix</span></code></li><li class="L7"><code class="lang-text"><span class="pln">gcc version </span><span class="lit">5.4</span><span class="pun">.</span><span class="lit">0</span><span class="pln"> </span><span class="lit">20160609</span><span class="pln"> </span><span class="pun">(</span><span class="typ">Ubuntu</span><span class="pln"> </span><span class="lit">5.4</span><span class="pun">.</span><span class="lit">0</span><span class="pun">-</span><span class="lit">6ubuntu1</span><span class="pun">~</span><span class="lit">16.04</span><span class="pun">.</span><span class="lit">9</span><span class="pun">)</span></code></li></ol></pre>
      <b>控制标准版本的编译选项</b>
      <ul>
        <li style="margin-left: 2em;">-ansi：告诉编译器遵守 C 语言的 ISO C90 标准。</li>
        <li style="margin-left: 2em;">-std=：通过使用一个参数来设置需要的标准。
          <ul>
            <li style="margin-left: 2em;">c89：支持 C89 标准。</li>
            <li style="margin-left: 2em;">iso9899:1999：支持 ISO C90 标准。</li>
            <li style="margin-left: 2em;">gnu89：支持 C89 标准。</li>
          </ul>
        </li>
      </ul>
      <b>控制标准版本的常量</b>
      这些常量（#define）可以通过编译器的命令行选项来设置，或者通过源代码总的 #define 语句来定义。
      <ul>
        <li style="margin-left: 2em;">__STRICT_ANSI__：强制使用 C 语言的 ISO 标准。这个常量通过命令行选项 -ansi 来定义。</li>
        <li style="margin-left: 2em;">_POSIX_C_SOURCE=2：启用由 IEEE Std1003.1 和 1003.2 标准定义的特性。</li>
        <li style="margin-left: 2em;">_BSD_SOURCE：启用 BSD 类型的特性。</li>
        <li style="margin-left: 2em;">_GNU_SOURCE：启用大量特性，其中包括 GNU 扩展。</li>
      </ul>
      <b>编译器的警告选项</b>
      <ul>
        <li style="margin-left: 2em;">-pedantic：除了启用用于检查代码是否遵守 C 语言标准的选项外，还关闭了一些不被标准允许的传统 C 语言结构，并且禁用所有的 GNU 扩展。</li>
        <li style="margin-left: 2em;">-Wformat：检查 printf 系列函数所使用的参数类型是否正确。</li>
        <li style="margin-left: 2em;">Wparentheses：检查是否总是提供了需要的圆括号。当想要检查一个复杂结构的初始化是否按照预期进行时，这个选项就很有用。</li>
        <li style="margin-left: 2em;">Wswitch-default：检查是否所有的 switch 语句都包含一个 default case。</li>
        <li style="margin-left: 2em;">Wunused：检查诸如声明静态函数但没有定义、未使用的参数和丢弃返回结果等情况。</li>
        <li style="margin-left: 2em;">Wall：启用绝大多数 gcc 的警告选项，包括所有以 -W 为前缀的选项。</li>
      </ul>
      <b>Address sanitizer</b>
      Address sanitizer 是一种用于检测内存错误的技术，GCC 从 4.8 版本开始支持了这一技术。ASan 在编译时插入额外指令到内存访问操作
      <br>中，同时通过 Shadow memory 来记录和检测内存的有效性。ASan 其实只是 Sanitizer 一系列工具中的一员，其他工具比如 <memory></memory>
      <br>leak 检测在 LeakSanitizer 中，uninitialized memory read 检测在 MemorySanitizer 中等等。
      <br>举个例子，很明显下面这个程序存在栈溢出：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-C"><span class="com">#include</span><span class="str">&lt;stdio.h&gt;</span></code></li><li class="L1"><code class="lang-C"><span class="kwd">void</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L2"><code class="lang-C"><span class="pln">    </span><span class="kwd">int</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">10</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">0</span><span class="pun">};</span></code></li><li class="L3"><code class="lang-C"><span class="pln">    </span><span class="kwd">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">[</span><span class="lit">11</span><span class="pun">];</span></code></li><li class="L4"><code class="lang-C"><span class="pun">}</span></code></li></ol></pre>
      编译时加上参数 -fsanitize=address，如果使用 Makefile，则将参数加入到 CFLAGS 中：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-text"><span class="pln">$ gcc </span><span class="pun">-</span><span class="pln">fsanitize</span><span class="pun">=</span><span class="pln">address santest</span><span class="pun">.</span><span class="pln">c</span></code></li></ol></pre>
      然后运行：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-text"><span class="pln">$ </span><span class="pun">./</span><span class="pln">a</span><span class="pun">.</span><span class="kwd">out</span></code></li><li class="L1"><code class="lang-text"><span class="pun">=================================================================</span></code></li><li class="L2"><code class="lang-text"><span class="pun">==</span><span class="lit">9399</span><span class="pun">==</span><span class="pln">ERROR</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AddressSanitizer</span><span class="pun">:</span><span class="pln"> stack</span><span class="pun">-</span><span class="pln">buffer</span><span class="pun">-</span><span class="pln">overflow on address </span><span class="lit">0x7ffc03f4d64c</span><span class="pln"> at pc </span><span class="lit">0x565515082ad6</span><span class="pln"> bp </span><span class="lit">0x7ffc03f4d5e0</span><span class="pln"> sp </span><span class="lit">0x7ffc03f4d5d0</span></code></li><li class="L3"><code class="lang-text"><span class="pln">READ of size </span><span class="lit">4</span><span class="pln"> at </span><span class="lit">0x7ffc03f4d64c</span><span class="pln"> thread T0</span></code></li><li class="L4"><code class="lang-text"><span class="pln">    </span><span class="com">#0 0x565515082ad5 in main (/home/firmy/a.out+0xad5)</span></code></li><li class="L5"><code class="lang-text"><span class="pln">    </span><span class="com">#1 0x7fb4c04c0f69 in __libc_start_main (/usr/lib/libc.so.6+0x20f69)</span></code></li><li class="L6"><code class="lang-text"><span class="pln">    </span><span class="com">#2 0x565515082899 in _start (/home/firmy/a.out+0x899)</span></code></li><li class="L7"><code class="lang-text"></code></li><li class="L8"><code class="lang-text"><span class="typ">Address</span><span class="pln"> </span><span class="lit">0x7ffc03f4d64c</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> located </span><span class="kwd">in</span><span class="pln"> stack of thread T0 at offset </span><span class="lit">76</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> frame</span></code></li><li class="L9"><code class="lang-text"><span class="pln">    </span><span class="com">#0 0x565515082989 in main (/home/firmy/a.out+0x989)</span></code></li><li class="L0"><code class="lang-text"></code></li><li class="L1"><code class="lang-text"><span class="pln">  </span><span class="typ">This</span><span class="pln"> frame has </span><span class="lit">1</span><span class="pln"> </span><span class="kwd">object</span><span class="pun">(</span><span class="pln">s</span><span class="pun">):</span></code></li><li class="L2"><code class="lang-text"><span class="pln">    </span><span class="pun">[</span><span class="lit">32</span><span class="pun">,</span><span class="pln"> </span><span class="lit">72</span><span class="pun">)</span><span class="pln"> </span><span class="str">'a'</span><span class="pln"> </span><span class="pun">&lt;==</span><span class="pln"> </span><span class="typ">Memory</span><span class="pln"> access at offset </span><span class="lit">76</span><span class="pln"> overflows </span><span class="kwd">this</span><span class="pln"> variable</span></code></li><li class="L3"><code class="lang-text"><span class="pln">HINT</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">this</span><span class="pln"> may be a </span><span class="kwd">false</span><span class="pln"> positive </span><span class="kwd">if</span><span class="pln"> your program uses some custom stack unwind mechanism </span><span class="kwd">or</span><span class="pln"> swapcontext</span></code></li><li class="L4"><code class="lang-text"><span class="pln">      </span><span class="pun">(</span><span class="pln">longjmp </span><span class="kwd">and</span><span class="pln"> C</span><span class="pun">++</span><span class="pln"> exceptions </span><span class="pun">*</span><span class="pln">are</span><span class="pun">*</span><span class="pln"> supported</span><span class="pun">)</span></code></li><li class="L5"><code class="lang-text"><span class="pln">SUMMARY</span><span class="pun">:</span><span class="pln"> </span><span class="typ">AddressSanitizer</span><span class="pun">:</span><span class="pln"> stack</span><span class="pun">-</span><span class="pln">buffer</span><span class="pun">-</span><span class="pln">overflow </span><span class="pun">(</span><span class="str">/home/</span><span class="pln">firmy</span><span class="pun">/</span><span class="pln">a</span><span class="pun">.</span><span class="kwd">out</span><span class="pun">+</span><span class="lit">0xad5</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> main</span></code></li><li class="L6"><code class="lang-text"><span class="typ">Shadow</span><span class="pln"> bytes around the buggy address</span><span class="pun">:</span></code></li><li class="L7"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1a70</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L8"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1a80</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L9"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1a90</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L0"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1aa0</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L1"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1ab0</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L2"><code class="lang-text"><span class="pun">=&gt;</span><span class="lit">0x1000007e1ac0</span><span class="pun">:</span><span class="pln"> f1 f1 f1 f1 </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pun">[</span><span class="pln">f2</span><span class="pun">]</span><span class="pln">f2 f2 </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L3"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1ad0</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L4"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1ae0</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L5"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1af0</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L6"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1b00</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L7"><code class="lang-text"><span class="pln">  </span><span class="lit">0x1000007e1b10</span><span class="pun">:</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span><span class="pln"> </span><span class="lit">00</span></code></li><li class="L8"><code class="lang-text"><span class="typ">Shadow</span><span class="pln"> </span><span class="kwd">byte</span><span class="pln"> legend </span><span class="pun">(</span><span class="pln">one shadow </span><span class="kwd">byte</span><span class="pln"> represents </span><span class="lit">8</span><span class="pln"> application bytes</span><span class="pun">):</span></code></li><li class="L9"><code class="lang-text"><span class="pln">  </span><span class="typ">Addressable</span><span class="pun">:</span><span class="pln">           </span><span class="lit">00</span></code></li><li class="L0"><code class="lang-text"><span class="pln">  </span><span class="typ">Partially</span><span class="pln"> addressable</span><span class="pun">:</span><span class="pln"> </span><span class="lit">01</span><span class="pln"> </span><span class="lit">02</span><span class="pln"> </span><span class="lit">03</span><span class="pln"> </span><span class="lit">04</span><span class="pln"> </span><span class="lit">05</span><span class="pln"> </span><span class="lit">06</span><span class="pln"> </span><span class="lit">07</span></code></li><li class="L1"><code class="lang-text"><span class="pln">  </span><span class="typ">Heap</span><span class="pln"> left redzone</span><span class="pun">:</span><span class="pln">       fa</span></code></li><li class="L2"><code class="lang-text"><span class="pln">  </span><span class="typ">Freed</span><span class="pln"> heap region</span><span class="pun">:</span><span class="pln">       fd</span></code></li><li class="L3"><code class="lang-text"><span class="pln">  </span><span class="typ">Stack</span><span class="pln"> left redzone</span><span class="pun">:</span><span class="pln">      f1</span></code></li><li class="L4"><code class="lang-text"><span class="pln">  </span><span class="typ">Stack</span><span class="pln"> mid redzone</span><span class="pun">:</span><span class="pln">       f2</span></code></li><li class="L5"><code class="lang-text"><span class="pln">  </span><span class="typ">Stack</span><span class="pln"> right redzone</span><span class="pun">:</span><span class="pln">     f3</span></code></li><li class="L6"><code class="lang-text"><span class="pln">  </span><span class="typ">Stack</span><span class="pln"> after </span><span class="kwd">return</span><span class="pun">:</span><span class="pln">      f5</span></code></li><li class="L7"><code class="lang-text"><span class="pln">  </span><span class="typ">Stack</span><span class="pln"> </span><span class="kwd">use</span><span class="pln"> after scope</span><span class="pun">:</span><span class="pln">   f8</span></code></li><li class="L8"><code class="lang-text"><span class="pln">  </span><span class="typ">Global</span><span class="pln"> redzone</span><span class="pun">:</span><span class="pln">          f9</span></code></li><li class="L9"><code class="lang-text"><span class="pln">  </span><span class="typ">Global</span><span class="pln"> init order</span><span class="pun">:</span><span class="pln">       f6</span></code></li><li class="L0"><code class="lang-text"><span class="pln">  </span><span class="typ">Poisoned</span><span class="pln"> </span><span class="kwd">by</span><span class="pln"> user</span><span class="pun">:</span><span class="pln">        f7</span></code></li><li class="L1"><code class="lang-text"><span class="pln">  </span><span class="typ">Container</span><span class="pln"> overflow</span><span class="pun">:</span><span class="pln">      fc</span></code></li><li class="L2"><code class="lang-text"><span class="pln">  </span><span class="typ">Array</span><span class="pln"> cookie</span><span class="pun">:</span><span class="pln">            ac</span></code></li><li class="L3"><code class="lang-text"><span class="pln">  </span><span class="typ">Intra</span><span class="pln"> </span><span class="kwd">object</span><span class="pln"> redzone</span><span class="pun">:</span><span class="pln">    bb</span></code></li><li class="L4"><code class="lang-text"><span class="pln">  </span><span class="typ">ASan</span><span class="pln"> </span><span class="kwd">internal</span><span class="pun">:</span><span class="pln">           fe</span></code></li><li class="L5"><code class="lang-text"><span class="pln">  </span><span class="typ">Left</span><span class="pln"> alloca redzone</span><span class="pun">:</span><span class="pln">     ca</span></code></li><li class="L6"><code class="lang-text"><span class="pln">  </span><span class="typ">Right</span><span class="pln"> alloca redzone</span><span class="pun">:</span><span class="pln">    cb</span></code></li><li class="L7"><code class="lang-text"><span class="pun">==</span><span class="lit">9399</span><span class="pun">==</span><span class="pln">ABORTING</span></code></li></ol></pre>
      确实检测出了问题。在实战篇中，为了更好地分析软件漏洞，我们可能会经常用到这个选项。
      <p>参考：<a href="https://en.wikipedia.org/wiki/AddressSanitizer" target="_blank">https://en.wikipedia.org/wiki/AddressSanitizer</a></p>
      <b>mcheck</b>
      <br>利用 mcheck 可以实现堆内存的一致性状态检查。其定义在 /usr/include/mcheck.h，是一个 GNU 扩展函数，原型如下：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;mcheck.h&gt;</span></code></li><li class="L1"><code class="lang-c"></code></li><li class="L2"><code class="lang-c"><span class="typ">int</span><span class="pln"> mcheck</span><span class="pun">(</span><span class="kwd">void</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">abortfunc</span><span class="pun">)(</span><span class="kwd">enum</span><span class="pln"> mcheck_status mstatus</span><span class="pun">));</span></code></li></ol></pre>
      可以看到参数是一个函数指针，但检查到堆内存异常时，通过该指针调用 abortfunc 函数，同时传入一个 mcheck_status 类型的参数。
      <br>举个例子，下面的程序存在 double-free 的问题：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdlib.h&gt;</span></code></li><li class="L1"><code class="lang-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdio.h&gt;</span></code></li><li class="L2"><code class="lang-c"></code></li><li class="L3"><code class="lang-c"><span class="kwd">void</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L4"><code class="lang-c"><span class="pln">    </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span></code></li><li class="L5"><code class="lang-c"><span class="pln">    p </span><span class="pun">=</span><span class="pln"> malloc</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">);</span></code></li><li class="L6"><code class="lang-c"><span class="pln">    fprintf</span><span class="pun">(</span><span class="pln">stderr</span><span class="pun">,</span><span class="pln"> </span><span class="str">"About to free\n"</span><span class="pun">);</span></code></li><li class="L7"><code class="lang-c"><span class="pln">    free</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span></code></li><li class="L8"><code class="lang-c"><span class="pln">    fprintf</span><span class="pun">(</span><span class="pln">stderr</span><span class="pun">,</span><span class="pln"> </span><span class="str">"About to free a second time\n"</span><span class="pun">);</span></code></li><li class="L9"><code class="lang-c"><span class="pln">    free</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span></code></li><li class="L0"><code class="lang-c"><span class="pln">    fprintf</span><span class="pun">(</span><span class="pln">stderr</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Finish\n"</span><span class="pun">);</span></code></li><li class="L1"><code class="lang-c"><span class="pun">}</span></code></li></ol></pre>
      通过设置参数 -lmcheck 来链接 mcheck 函数：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-text"><span class="pln">$ gcc </span><span class="pun">-</span><span class="pln">lmcheck t_mcheck</span><span class="pun">.</span><span class="pln">c</span></code></li><li class="L1"><code class="lang-text"><span class="pln">$ </span><span class="pun">./</span><span class="pln">a</span><span class="pun">.</span><span class="kwd">out</span></code></li><li class="L2"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free</span></code></li><li class="L3"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free a second time</span></code></li><li class="L4"><code class="lang-text"><span class="pln">block freed twice</span></code></li><li class="L5"><code class="lang-text"><span class="typ">Aborted</span><span class="pln"> </span><span class="pun">(</span><span class="pln">core dumped</span><span class="pun">)</span></code></li></ol></pre>
      还可以通过设置环境变量 MALLOC_CHECK_ 来实现，这样就不需要重新编译程序。
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-text"><span class="pln">$ gcc mcheck</span><span class="pun">.</span><span class="pln">c</span></code></li><li class="L1"><code class="lang-text"><span class="pln">$ </span><span class="com">#检查到错误时不作任何提示</span></code></li><li class="L2"><code class="lang-text"><span class="pln">$ MALLOC_CHECK_</span><span class="pun">=</span><span class="lit">0</span><span class="pln"> </span><span class="pun">./</span><span class="pln">a</span><span class="pun">.</span><span class="kwd">out</span></code></li><li class="L3"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free</span></code></li><li class="L4"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free a second time</span></code></li><li class="L5"><code class="lang-text"><span class="typ">Finish</span></code></li><li class="L6"><code class="lang-text"><span class="pln">$ </span><span class="com">#检查到错误时打印一条信息到标准输出</span></code></li><li class="L7"><code class="lang-text"><span class="pln">$ MALLOC_CHECK_</span><span class="pun">=</span><span class="lit">1</span><span class="pln"> </span><span class="pun">./</span><span class="pln">a</span><span class="pun">.</span><span class="kwd">out</span></code></li><li class="L8"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free</span></code></li><li class="L9"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free a second time</span></code></li><li class="L0"><code class="lang-text"><span class="pun">***</span><span class="pln"> </span><span class="typ">Error</span><span class="pln"> </span><span class="kwd">in</span><span class="pln"> </span><span class="str">`./a.out': free(): invalid pointer: 0x0000000001fb9010 ***</span></code></li><li class="L1"><code class="lang-text"><span class="str">Finish</span></code></li><li class="L2"><code class="lang-text"><span class="str">$ #检查到错误时直接中止程序</span></code></li><li class="L3"><code class="lang-text"><span class="str">$ MALLOC_CHECK_=2 ./a.out</span></code></li><li class="L4"><code class="lang-text"><span class="str">About to free</span></code></li><li class="L5"><code class="lang-text"><span class="str">About to free a second time</span></code></li><li class="L6"><code class="lang-text"><span class="str">Aborted (core dumped)</span></code></li></ol></pre>
      具体参考 man 3 mcheck 和 man 3 mallopt。
      <br>glibc 还提供了 mtrace() 和 muntrace() 函数分别在程序中打开和关闭对内存分配调用进行跟踪的功能。这些函数需要与环境变量
      <br>MALLOC_TRACE 配合使用，该变量定义了写入跟踪信息的文件名。在被调用时，mtrace() 会检查是否定义了该文件，又是否可以读写
      <br>该文件。如果一切正常，那么会在文件里跟踪和记录所有对 malloc 系列函数的调用。由于生成的文件不易于理解，还提供了脚本（mtrace）用于分析文件，并生成易于理解的汇总报告。
      <br>将上面的例子修改一下：
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdlib.h&gt;</span></code></li><li class="L1"><code class="lang-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;stdio.h&gt;</span></code></li><li class="L2"><code class="lang-c"><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;mcheck.h&gt;</span></code></li><li class="L3"><code class="lang-c"></code></li><li class="L4"><code class="lang-c"><span class="kwd">void</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span></code></li><li class="L5"><code class="lang-c"><span class="pln">    </span><span class="kwd">char</span><span class="pln"> </span><span class="pun">*</span><span class="pln">p</span><span class="pun">;</span></code></li><li class="L6"><code class="lang-c"></code></li><li class="L7"><code class="lang-c"><span class="pln">    mtrace</span><span class="pun">();</span></code></li><li class="L8"><code class="lang-c"></code></li><li class="L9"><code class="lang-c"><span class="pln">    calloc</span><span class="pun">(</span><span class="lit">16</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">);</span></code></li><li class="L0"><code class="lang-c"><span class="pln">    fprintf</span><span class="pun">(</span><span class="pln">stderr</span><span class="pun">,</span><span class="pln"> </span><span class="str">"calloc some chunks that will not be freed\n"</span><span class="pun">);</span></code></li><li class="L1"><code class="lang-c"></code></li><li class="L2"><code class="lang-c"><span class="pln">    p </span><span class="pun">=</span><span class="pln"> malloc</span><span class="pun">(</span><span class="lit">1000</span><span class="pun">);</span></code></li><li class="L3"><code class="lang-c"><span class="pln">    fprintf</span><span class="pun">(</span><span class="pln">stderr</span><span class="pun">,</span><span class="pln"> </span><span class="str">"About to free\n"</span><span class="pun">);</span></code></li><li class="L4"><code class="lang-c"><span class="pln">    free</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span></code></li><li class="L5"><code class="lang-c"><span class="pln">    fprintf</span><span class="pun">(</span><span class="pln">stderr</span><span class="pun">,</span><span class="pln"> </span><span class="str">"About to free a second time\n"</span><span class="pun">);</span></code></li><li class="L6"><code class="lang-c"><span class="pln">    free</span><span class="pun">(</span><span class="pln">p</span><span class="pun">);</span></code></li><li class="L7"><code class="lang-c"><span class="pln">    fprintf</span><span class="pun">(</span><span class="pln">stderr</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Finish\n"</span><span class="pun">);</span></code></li><li class="L8"><code class="lang-c"></code></li><li class="L9"><code class="lang-c"><span class="pln">    muntrace</span><span class="pun">();</span></code></li><li class="L0"><code class="lang-c"><span class="pun">}</span></code></li></ol></pre>
      <pre style="margin-left: 2em;"><ol class="linenums"><li class="L0"><code class="lang-text"><span class="pln">$ gcc t_mtrace</span><span class="pun">.</span><span class="pln">c</span></code></li><li class="L1"><code class="lang-text"><span class="pln">$ </span><span class="kwd">export</span><span class="pln"> MALLOC_TRACE</span><span class="pun">=</span><span class="str">/tmp/</span><span class="pln">t</span></code></li><li class="L2"><code class="lang-text"><span class="pln">$ </span><span class="pun">./</span><span class="pln">a</span><span class="pun">.</span><span class="kwd">out</span></code></li><li class="L3"><code class="lang-text"><span class="pln">calloc some chunks that will </span><span class="kwd">not</span><span class="pln"> be freed</span></code></li><li class="L4"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free</span></code></li><li class="L5"><code class="lang-text"><span class="typ">About</span><span class="pln"> to free a second time</span></code></li><li class="L6"><code class="lang-text"><span class="typ">Finish</span></code></li><li class="L7"><code class="lang-text"><span class="pln">$ mtrace </span><span class="pun">/</span><span class="pln">tmp</span><span class="pun">/</span><span class="pln">t</span></code></li><li class="L8"><code class="lang-text"><span class="pun">-</span><span class="pln"> </span><span class="lit">0x000055e427cde7b0</span><span class="pln"> </span><span class="typ">Free</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> was never alloc</span><span class="str">'d 0x55e425da287c</span></code></li><li class="L9"><code class="lang-text"></code></li><li class="L0"><code class="lang-text"><span class="str">Memory not freed:</span></code></li><li class="L1"><code class="lang-text"><span class="str">-----------------</span></code></li><li class="L2"><code class="lang-text"><span class="str">           Address     Size     Caller</span></code></li><li class="L3"><code class="lang-text"><span class="str">0x000055e427cde6a0    0x100  at 0x55e425da27f6</span></code></li></ol></pre>
      于是 double-free 和内存泄漏被检测出来了。
      <h3>参考资料</h3>
      <ul>
        <li style="margin-left: 2em;"><a href="https://gcc.gnu.org/onlinedocs/" target="_blank">GCC online documentation</a></li>
      </ul>
      <el-divider></el-divider>

      <h3>在 GCC 编译参数中，以下哪个选项用于指定生成的目标文件名？</h3>
      <el-radio-group v-model="radio">
        <el-radio :label="1">-I</el-radio>
        <el-radio :label="2">-L</el-radio>
        <el-radio :label="3">-o</el-radio>
        <el-radio :label="4">-g</el-radio>
        <el-button type="primary" plain :disabled="isButtonDisabled" @click="check(radio)">检查</el-button>
      </el-radio-group>
    </div>
    <el-divider></el-divider>

  </div>
</template>

<style scoped>

</style>